Type CalCoreMorphTrack
	
	Field m_morphName:String
	Field m_keyframes:CalCoreMorphKeyframe[]
	Field m_keyframesToDelete:CalCoreMorphKeyframe[]
	
	Method New()
		m_morphName = "morph"
		m_keyframes = m_keyframes[..0]
		m_keyframesToDelete = m_keyframesToDelete[..0]
	End Method
	
	Function Build:CalCoreMorphTrack(mname:String="morph")
		Local mt:CalCoreMorphTrack = New CalCoreMorphTrack
		mt.m_morphName = mname
		Return mt
		
	End Function



	Method addCoreMorphKeyframe:Byte(pCoreMorphKeyframe:CalCoreMorphKeyframe)

		m_keyframes = m_keyframes[..m_keyframes.length+1]
		m_keyframes[m_keyframes.length-1] = pCoreMorphKeyframe
		m_keyframesToDelete = m_keyframesToDelete[..m_keyframesToDelete.length+1]
		m_keyframesToDelete[m_keyframesToDelete.length-1] = pCoreMorphKeyframe
		Local idx:Int = m_keyframes.length - 1
		While idx > 0 And m_keyframes[idx].getTime() < m_keyframes[idx - 1].getTime()
			Local a:CalCoreMorphKeyframe = m_keyframes[idx]
			Local b:CalCoreMorphKeyframe = m_keyframes[idx - 1]
			m_keyframes[idx - 1] = a
			m_keyframes[idx] = b
			idx = idx - 1
		Wend
	
		Return True
	End Method


	Method getState:Byte(time:Float,weight:Float)

		Local reqframe:Int = getUpperBound(time)
		' get the keyframe after the requested time
		Local iteratorCoreMorphKeyframeAfter:CalCoreMorphKeyframe = m_keyframes[reqframe]
		
		' check If the time is after the last keyframe
		If iteratorCoreMorphKeyframeAfter = m_keyframes[m_keyframes.length-1] Then
		
			' Return the last keyframe state
			'--iteratorCoreMorphKeyframeAfter;
			weight = m_keyframes[m_keyframes.length-2].getWeight();
		
			Return True
		EndIf
		
		' check If the time is before the first keyframe
		If iteratorCoreMorphKeyframeAfter = m_keyframes[0] Then
		
			'Return the first keyframe state
			weight = m_keyframes[0].getWeight();
		
			Return True
		EndIf
		
		' get the keyframe before the requested one
		Local iteratorCoreMorphKeyframeBefore:CalCoreMorphKeyframe = m_keyframes[reqframe-1]
		'--iteratorCoreMorphKeyframeBefore;
		
		' get the two keyframe pointers
		Local pCoreMorphKeyframeBefore:CalCoreMorphKeyframe = iteratorCoreMorphKeyframeBefore
		Local pCoreMorphKeyframeAfter:CalCoreMorphKeyframe = iteratorCoreMorphKeyframeAfter
		
		' calculate the blending factor between the two keyframe states
		Local blendFactor:Float
		blendFactor = (time - pCoreMorphKeyframeBefore.getTime()) / (pCoreMorphKeyframeAfter.getTime() - pCoreMorphKeyframeBefore.getTime())
		
		' blend between the two keyframes
		weight = pCoreMorphKeyframeBefore.getWeight()
		Local otherWeight:Float = pCoreMorphKeyframeAfter.getWeight()
		weight = weight+blendFactor * (otherWeight-weight)
		
		Return True
	End Method



	Method getUpperBound:Int(time:Float)
	
		lowerBound:Int = 0
		upperBound:Int = m_keyframes.length-1
		
		While lowerBound<upperBound-1
		
			Local middle:Int = (lowerBound+upperBound)/2
		
			If time >= m_keyframes[middle].getTime() 
		
				lowerBound=middle
		
			Else
		
				upperBound=middle
			EndIf
		Wend
		
		Return upperBound
	
	End Method

	Method setMorphName(morphname:String)
		m_morphName = morphname
	End Method	
	
	Method getMorphName:String()
		Return m_morphName
	End Method
	
	Method getCoreMorphKeyframeCount:Int()
		Return m_keyframes.length
	End Method
	
	Method reserve(size:Int)
		m_keyframes = m_keyframes[..size]
	End Method
	
	Method getCoreMorphKeyframe:CalCoreMorphKeyframe(idx:Int)
		Return m_keyframes[idx]
	End Method
	
	Method scale(factor:Float)
		
	    For Local keyframeId:Int = 0 To m_keyframes.length-1
	    
	        Local weight:Float = m_keyframes[keyframeId].getWeight()
	        weight=weight*factor
	        m_keyframes[keyframeId].setWeight(weight)
	    Next		
		
		
	End Method
	
	
	Method getVectorCoreMorphKeyframes:CalCoreMorphKeyframe[]()
		Return m_keyframes
	End Method
	
End Type
